/**
 * request 网络请求工具
 * 更详细的 api 文档: https://github.com/umijs/umi-request
 */
import {extend} from 'umi-request';
import {message} from 'antd';
import {assign, omit, isFunction, isObject, isString, isEmpty} from 'lodash-es';
import {urlEncode} from 'jh-utils';
import {hadLocale, myFormatMessage} from '@/utils/localeUtils';
// import {formatTip} from "@/tipConfig";
import {loginApis as apiConfig} from "@/services/login";

/**
 * 请求超时时间5分钟
 * @type {number}
 */
const reqTimeOut = (1000 * 60) * 5;
// const  reqTimeOut = 500;

/**
 * 异常处理程序
 */
const errorHandler = (error) => {
  // console.log('errorHandler', error);
  if (error && error.message && -1 !== error.message.indexOf('timeout')) {
    // '请求超时，稍后再试'
    message.error(myFormatMessage('504'));
    return null;
  }

  const {request, response, data} = error;
  // console.log('response', response, data);
  if (response && 401 != response.status) { // 401 标识登录过期，会在 isLogin 中处理；所以这里不做提示。
    let errorText = '';

    if (data && data.states && data.states.message) {
      errorText = `${data.states.message} - ${response.status}`;

    } else {
      errorText = hadLocale(response.status) ? myFormatMessage(`${response.status}`) : ('Request fail' || response.statusText);
    }

    if (isString(data)) {
      error.data = {errorText, data}

    } else if (data) {
      data.errorText = errorText;
    }
    // const { status } = response;
    if (false !== request.options.needTip) {
      message.error(`${myFormatMessage('global.request.fail')}: ${errorText}`, 2);
    }

  }
  return error;
};

export const isLogin = (res, showTip = true) => {
  // console.log('isLogin res', res)
  // let rspData = res ? res.data : null;
  // let noLogined = rspData && 'undefined' !== typeof rspData.isAuthenticated
  //   && !rspData.isAuthenticated
  //   && 'Login Failure' === rspData.detailMessage;
  let noLogined = res && res.response && 401 == res.response.status; // http 401 错误时，表示登录过期

  // header 没有 TOKEN，也表示登录过期
  // if (!isEmpty(res) && res.response && res.response.headers) {
  //   const token = res.response.headers.get('TOKEN');
  //   // console.log('>>> token', token);
  //   if (isEmpty(token)) {
  //     noLogined = true;
  //   }
  // }

  // console.log('noLogined', noLogined);

  if (showTip && noLogined) {
    // 处理登录过期逻辑。弹出登录过期提示，然后弹出登录弹框
    window.dealLoginTimeout && window.dealLoginTimeout();

  } else {
    return !noLogined;
  }

};

export const failHandler = (response, isReturn) => {
  // console.log('failHandler rsp', response);
  let errMsg = '';

  if (isObject(response) && 'undefined' !== typeof response.status) {

    if (200 !== response.status) {
      const tipMsg = "";//formatTip(response.status, response.parameters);
      errMsg = tipMsg || `${myFormatMessage('global.request.fail')}:${response.status}`;
    }

  } else if (response.errorText) {
    errMsg = response.errorText;

  } else if (isEmpty(response)) {
    errMsg = `${myFormatMessage('global.request.fail')}`;
  }
  // console.log('failHandler errMsg', errMsg)

  if (true === isReturn) {
    return errMsg;
  }

  if (!isEmpty(errMsg)) {
    message.error(errMsg);
  }
  return response;
};

/**
 * 配置request请求时的默认参数
 */
export const request = extend({
  // prefix: process.env.apiPrefix,
  errorHandler, // 默认错误处理
  credentials: 'include', // 默认请求是否带上cookie
  getResponse: true,
});

request.use(async (ctx, next) => {
  const {req} = ctx;
  const {options} = req;
  let api = req.url;

  if (isEmpty(api) || (isString(api) && 0 !== api.indexOf('/api'))) {
    return Promise.resolve();
  }

  await next();

  const {res} = ctx;

  // 统一将接口的错误码字符串 200 转换为数字 200
  if (isObject(res) && res.data && 'undefined' !== typeof res.data.status) {
    if ('200' == res.data.status) {
      res.data.status = parseInt(res.data.status);
    }

    if (options && options.signal) {
      options.signal.noAbort = true;
    }
  }
});

function beforeReq({options}) {
  let hide;
  if (options && true === options.needLoading) {
    hide = message.loading(myFormatMessage('global.request.loading'), 0);
  }
  return {hide};
}

function afterReq({api, res, options, hide}) {
  isFunction(hide) && hide();

  if (api !== apiConfig.logout) {
    // 如果没有登陆，则跳转到登录页
    isLogin(res);
  }

  let httpStatus = res && res.response ? res.response.status : null;
  let rsp = res ? res.data : null;

  // 错误提示
  if (200 === httpStatus && options && false !== options.needTip) {
    failHandler(rsp, false, res);
  }

  return res ? res.data : null;
}

export default request;

//---------------------------
//-- 异步请求常用方法
//---------------------------

/**
 * get 请求
 * @param api api 地址
 * @param params （可选）参数
 * @param options （可选）request 的 options
 * @returns {Promise<any>}
 */
export const reqGet = (api, params = {}, options = {}) => {
  let fOption = {
    headers: {Accept: 'application/json;charset=UTF-8'},
    params: {
      ...omit(params, ['signal', 'needLoading', 'needTip']),
    },
    timeout: reqTimeOut,
    ...assign({signal: params.signal, needTip: params.needTip}, options),
  };
  let {hide} = beforeReq({options: fOption});

  return request.get(api, fOption).then((res) => (
    afterReq({api, res, options: fOption, hide})
  )).catch(e => {
    console.error('e', e);
  });

};

/**
 * post 提交 json 数据，Content-type=application/json
 * @param api String api 地址
 * @param data Object 提交数据对象
 * @param options Object （可选）request 的 options
 * @returns {Promise<any>}
 */
export const jsonPost = (api, data = {}, options = {}) => {
  let fOption = {
    method: 'post',
    timeout: reqTimeOut,
    // requestType: 'form',
    data: {
      ...omit(data, ['signal', 'noLoading', 'needLoading', 'needTip']),
    },
    ...assign({signal: data.signal, needTip: data.needTip}, options),
  };
  let {hide} = beforeReq({options: fOption});

  return request(api, fOption).then((res) => (
    afterReq({api, res, options: fOption, hide})
  )).catch(e => {
    console.error('e', e);
  });
};

/**
 * post 提交 Form Data 数据，Content-type=application/x-www-form-urlencoded
 * @param api String api 地址
 * @param data Object 提交数据对象
 * @param options Object （可选）request 的 options
 * @returns {Promise<any>}
 */
export const formPost = (api, data = {}, options = {}) => {
  const fData = {
    ...omit(data, ['signal', 'needLoading', 'needTip']),
    // locale: 'en-US' !== window.localStorage.getItem('umi_locale') ? 'zh' : 'en', // 加上国际化参数

  };
  let fOption = {
    method: 'post',
    timeout: reqTimeOut,
    headers: {
      'Content-type': 'application/json;charset=UTF-8',
      // 'Content-type':'application/x-www-form-urlencoded',
      Accept: 'application/json;charset=UTF-8',
    },
    body: urlEncode(fData),
    // data: { ...omit(data, ['signal', 'needLoading']) },
    ...assign({signal: data.signal, needTip: data.needTip}, options),
  };
  let {hide} = beforeReq({options: fOption});

  return request(api, fOption).then((res) => (
    afterReq({api, res, options: fOption, hide})
  )).catch(e => {
    console.error('e', e);
  });
};

//---------------------------
//-- 异步请求控制器
//---------------------------

/**
 * new 异步请求控制器
 */
export const newAbortCtrl = () => {
  if ('AbortController' in window) {
    return new window.AbortController();
  } else {
    console.warn('浏览器不支持 AbortController，将无法中止异步请求');
    return {};
  }
};

/**
 * 终断 request 请求
 * @param abortCtrl
 */
export const abortFetch = (abortCtrl) => {
  if ('AbortController' in window) {

    if (abortCtrl && true !== abortCtrl.signal.noAbort) {
      abortCtrl.abort();
    }
  } else {
    console.warn('浏览器不支持 AbortController，将无法中止异步请求');
    return {};
  }
};
